﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MyAlbum.Data;
using MyAlbum.Utility;
using MyAlbum.Model;

namespace MyAlbum.Services
{
    public class BlogService : IBlogService
    {
        private IBlogRepository _blogRepository;
        private IUser _user;
        public BlogService(IBlogRepository blogRepository, IUser user)
        {
            this._blogRepository = blogRepository;
            this._user = user;
        }
        public int CountPosts()
        {
            return this._blogRepository.CountPosts();
        }
        public void AddComment(Reply reply)
        {
            Assert.IsNotNull(reply);
            BlogML.Xml.BlogMLComment comment = new BlogML.Xml.BlogMLComment();
            reply.TimeStamp = DateTime.UtcNow;
            reply.Id = Guid.NewGuid().ToString("N");
            Copy(reply, comment);

            this._blogRepository.AddComment(reply.EntryId, comment);
        }

        private void Copy(Reply reply, BlogML.Xml.BlogMLComment comment)
        {
            comment.Content.Text = reply.Body;
            comment.UserEMail = reply.Email;
            comment.UserName = reply.UserName;
            comment.Title = reply.Subject;
            comment.Approved = reply.IsApproved;
            comment.DateCreated = reply.TimeStamp;
            comment.ID = reply.Id;
        }

        private void Copy(BlogML.Xml.BlogMLComment comment, Reply reply)
        {
            reply.Body = comment.Content.Text;
            reply.Email = comment.UserEMail;
            reply.UserName = comment.UserName;
            reply.Subject = comment.Title;
            reply.IsApproved = comment.Approved;
            reply.TimeStamp = comment.DateCreated;
            reply.Id = comment.ID;
        }
        public string AddPost(PostEntry post, Uri host, IValidationSummary validationSummary)
        {

            Assert.IsNotNull(post);
            BlogML.Xml.BlogMLPost postML = new BlogML.Xml.BlogMLPost();
            Copy(post, postML);
            post.DateCreated = DateTime.UtcNow;
            post.ID = Guid.NewGuid().ToString("N");

            if (string.IsNullOrEmpty(post.Title))
            {
                validationSummary.AddError("Title", "Post title must have a value");
            }

            this._blogRepository.AddPost(postML);
            return post.ID;
        }

        private void Copy(PostEntry post, BlogML.Xml.BlogMLPost postML)
        {
            postML.Title = post.Title;
            if (!string.IsNullOrEmpty(post.UserName))
            {
                postML.Authors.Add(new BlogML.Xml.BlogMLAuthorReference()
                {
                    Ref = post.UserName
                });
            }
            else
            {
                postML.Authors.Add(new BlogML.Xml.BlogMLAuthorReference()
                {
                    Ref = this._user.Name
                });
            }
            postML.DateCreated = post.DateCreated;
            postML.Approved = post.Approved;
            postML.Content = new BlogML.Xml.BlogMLContent()
            {
                Text = post.Content
            };
            postML.ID = post.ID;
            postML.PostType = BlogML.BlogPostTypes.Normal;

            foreach (var item in post.Tags)
            {
                postML.Categories.Add(new BlogML.Xml.BlogMLCategoryReference()
                {
                    Ref = item.Name
                });
            }
        }
        private IEnumerable<PostEntry> Cast(IEnumerable<BlogML.Xml.BlogMLPost> items)
        {
            List<PostEntry> result = new List<PostEntry>();
            foreach (var item in items)
            {
                PostEntry pe = new PostEntry();
                Copy(item, pe);
                result.Add(pe);
            }
            return result;
        }
        private void Copy(BlogML.Xml.BlogMLPost postML, PostEntry post)
        {
            post.Title = postML.Title;
            post.UserName = postML.Authors.Count == 0 ? null : postML.Authors[0].Ref;
            post.DateCreated = postML.DateCreated;
            post.Approved = postML.Approved;
            post.Content = postML.Content.Text;
            post.ID = postML.ID;
            List<Tag> tags = new List<Tag>();
            foreach (BlogML.Xml.BlogMLCategoryReference item in postML.Categories)
            {

                tags.Add(new Tag()
                {
                    Name = item.Ref
                });
            }
            post.Tags = tags;
            List<Reply> replies = new List<Reply>();
            foreach (BlogML.Xml.BlogMLComment item in postML.Comments)
            {
                Reply r = new Reply();
                Copy(item, r);
                r.EntryId = post.ID;
                replies.Add(r);
            }
            post.Replies = replies;
        }

        public void DeleteComment(string postId, string commentId)
        {
            if (this._user.AllowActions())
            {
                this._blogRepository.DeleteComment(postId, commentId);
            }
            else
            {

            }
        }
        public void DeletePost(string postId)
        {
            this._blogRepository.DeletePost(postId);
        }

        public PostEntry GetPost(string postId)
        {
            PostEntry post = new PostEntry();
            Copy(this._blogRepository.GetPost(postId), post);
            post.DateCreated = post.DateCreated.ToUniversalTime();
            post.DateModified = post.DateModified.ToUniversalTime();
            return post;
        }
        public System.Collections.Generic.IEnumerable<PostEntry> GetPosts(int pageIndex, int pageSize, DateTime? sinceDate)
        {
            if (sinceDate.HasValue)
            {
                sinceDate = sinceDate.Value.ToUniversalTime();
            }
            pageIndex = pageIndex < 1 ? 1 : pageIndex;
            return Cast(AdjustDatesToLocal(this._blogRepository.GetPosts(pageIndex, pageSize, sinceDate)).Reverse());

        }

        private IEnumerable<BlogML.Xml.BlogMLPost> AdjustDatesToLocal(IEnumerable<BlogML.Xml.BlogMLPost> items)
        {
            foreach (var item in items)
            {
                item.DateModified = item.DateModified.ToUniversalTime();
                item.DateCreated = item.DateCreated.ToUniversalTime();
            }
            return items;
        }
        public System.Collections.Generic.IEnumerable<PostEntry> GetPosts(Tag tag, DateTime? sinceDate, int maxCount)
        {
            if (sinceDate.HasValue)
            {
                sinceDate = sinceDate.Value.ToUniversalTime();
            }
            return Cast(AdjustDatesToLocal(this._blogRepository.GetPosts(new BlogML.Xml.BlogMLCategory() { Title = tag.Name }, sinceDate, maxCount)).Reverse());
        }
        public System.Collections.Generic.IEnumerable<PostEntry> GetPosts(string searchFilter, DateTime? sinceDate, int maxCount)
        {
            if (sinceDate.HasValue)
            {
                sinceDate = sinceDate.Value.ToUniversalTime();
            }
            return Cast(AdjustDatesToLocal(this._blogRepository.GetPosts(searchFilter, sinceDate, maxCount)).Reverse());
        }
        public void UpdateComment(Reply reply)
        {
            Assert.IsNotNull(reply);
            BlogML.Xml.BlogMLComment comment = new BlogML.Xml.BlogMLComment();
            Copy(reply, comment);
            comment.DateModified = DateTime.UtcNow;
            this._blogRepository.UpdateComment(reply.EntryId, comment);
        }
        public void UpdatePost(PostEntry post, IValidationSummary validationSummary)
        {
            Assert.IsNotNull(post);

            if (string.IsNullOrEmpty(post.Title))
            {
                validationSummary.AddError("Title", "Post title must have a value");
            }
            if (string.IsNullOrEmpty(post.ID))
            {
                validationSummary.AddError("ID", "Post ID must have a value");
            }
            if (validationSummary.IsValid)
            {
                BlogML.Xml.BlogMLPost postML = new BlogML.Xml.BlogMLPost();
                Copy(post, postML);
                if (post.DateCreated == DateTime.MinValue)
                {
                    post.DateCreated = DateTime.UtcNow;
                }
                else
                {
                    post.DateCreated = post.DateCreated.ToUniversalTime();
                }
                postML.DateModified = DateTime.UtcNow;
                this._blogRepository.UpdatePost(postML);
            }
        }

        #region IBlogService Members


        public List<Tag> GetCategories()
        {
            return this._blogRepository.GetCategories();
        }

        #endregion
    }
}
